package com.osilon.asm;

import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.MethodNode;

public class InsnSearcher {
	private AbstractInsnNode[] nodes;
	private int idx = -1;
	
	public InsnSearcher(MethodNode method) {
		nodes = method.instructions.toArray();
	}
	
	public LdcInsnNode nextLdc() {
		return nextLdc(null);
	}
	
	public LdcInsnNode nextLdc(Object cst) {
		for(int x = idx + 1; x < nodes.length; x++) {
			if(nodes[x] instanceof LdcInsnNode) {
				LdcInsnNode node = (LdcInsnNode) nodes[x];
				
				if(cst == null || node.cst.equals(cst)) {
					idx = x;
					return node;
				}
			}
		}
		
		return null;
	}
	
	public MethodInsnNode nextInvoke(int type) {
		for(int x = idx + 1; x < nodes.length; x++) {
			if(nodes[x] instanceof MethodInsnNode) {
				MethodInsnNode node = (MethodInsnNode) nodes[x];
				
				if(node.getOpcode() == type) {
					idx = x;
					return node;
				}
			}
		}
		
		return null;
	}
	
	public FieldInsnNode prevFieldInsn(int opcode) {
		for(int x = idx - 1; x > -1; x--) {
			if(nodes[x] instanceof FieldInsnNode) {
				FieldInsnNode fin = (FieldInsnNode) nodes[x];
				
				if(fin.getOpcode() == opcode) {
					idx = x;
					return fin;
				}
			}
		}
		
		return null;
	}
	
	public FieldInsnNode nextFieldInsn(int opcode) {
		for(int x = idx + 1; x < nodes.length; x++) {
			if(nodes[x] instanceof FieldInsnNode) {
				FieldInsnNode fin = (FieldInsnNode) nodes[x];
				
				if(fin.getOpcode() == opcode) {
					idx = x;
					return fin;
				}
			}
		}
		
		return null;
	}
}
